/**
 *    Copyright (C) 2008, 2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_BTREE_PAGES_DISPATCHERS_HPP
#define	_CUBEFS_CORE_BTREE_PAGES_DISPATCHERS_HPP


#include <cubefs/core/btree/pages/dispatchers/defs.hpp>
#include <cubefs/core/btree/pages/dispatchers/tools.hpp>
#include <cubefs/core/btree/pages/dispatchers/factory.hpp>
#include <cubefs/core/btree/pages/dispatchers/node_dispatcher.hpp>
#include <cubefs/core/btree/pages/dispatchers/builder.hpp>

//namespace cubefs    {
//namespace core      {
//namespace btree     {
//namespace pages     {
//
//using namespace cubefs::core::tools::types::relation;
//using cubefs::core::TypeList;
//
//const BigInt ANY_LEVEL = 0x7fff;
//
//typedef enum {ROOT, LEAF, LEVEL} NodeDescriptorColumns;
//
//template <bool Root_, bool Leaf_, BigInt Level_>
//struct NodeDescriptor {
//    static const bool   Root  =      Root_;
//    static const bool   Leaf  =      Leaf_;
//    static const BigInt Level =      Level_;
//};
//
//
//template <Int Name, typename ColumnType, typename Record> struct ValueProvider;
//
//typedef RelationMetadata<
//            TypeListTool<Column<ROOT, Int>, Column<LEAF, Int>, Column<LEVEL, Short> >::List,
//            ValueProvider
//>                                                                               NodeDescriptorMetadata;
//
//
//template <typename ColumnType, typename Record>
//struct ValueProvider<ROOT, ColumnType, Record>:
//    public StaticValue<ColumnType, Record::Descriptor::Root> {};
//
//template <typename ColumnType, typename Record>
//struct ValueProvider<LEAF, ColumnType, Record>:
//    public StaticValue<ColumnType, Record::Descriptor::Leaf> {};
//
//template <typename ColumnType, typename Record>
//struct ValueProvider<LEVEL, ColumnType, Record>:
//    public StaticValue<ColumnType, Record::Descriptor::Level> {};
//
//
//template <
//        typename Expression,
//        typename Relation
//>
//class NodeFilter: public Filter<NodeDescriptorMetadata, Expression, Relation> {};
//
//
//template <typename List, typename Result = NullType> struct LevelListBuilder;
//
//template <typename Head, typename Tail, typename Result>
//struct LevelListBuilder<TypeList<Head, Tail>, Result> {
//    static const BigInt Level = Head::Descriptor::Level;
//private:
//    typedef TypeList<TypeCode<Level>, Result>                                   NewResult;
//public:
//    typedef typename LevelListBuilder<Tail, NewResult>::List                    List;
//};
//
//template <typename Result>
//struct LevelListBuilder<NullType, Result> {
//    typedef typename RemoveDuplicatesTool<Result>::Result                       List;
//};
//
//
//
//namespace intrnl {
//
//template <
//        typename List,
//        typename SrcList,
//        typename Result = NullType
//>
//class Node2NodeMapBuilderTool;
//
//template <
//        typename SrcList,
//        typename Result
//>
//class Node2NodeMapBuilderTool<NullType, SrcList, Result> {
//public:
//    typedef Result                                                              Map;
//};
//
//template <
//        typename Head,
//        typename Tail,
//        typename SrcList,
//        typename Result
//>
//class Node2NodeMapBuilderTool<TypeList<Head, Tail>, SrcList, Result> {
//    static const bool   Root  = Head::Descriptor::Root;
//    static const bool   Leaf  = Head::Descriptor::Leaf;
//    static const BigInt Level = Head::Descriptor::Level;
//
//    typedef typename NodeFilter<ValueOp<ROOT,  EQ, bool, !Root>,  SrcList>::Result         InverseRootList;
//    typedef typename NodeFilter<ValueOp<LEAF,  EQ, bool,  Leaf>,  InverseRootList>::Result SameLeafList;
//    typedef typename NodeFilter<ValueOp<LEVEL, EQ, Short, Level>, SameLeafList>::Result    SameLevelList;
//
//    typedef TypeList<
//                Pair<
//                    Head,
//                    typename SameLevelList::Head
//                >,
//                Result
//            >                                                                   NewResult;
//
//public:
//    typedef typename Node2NodeMapBuilderTool<Tail, SrcList, NewResult>::Map     Map;
//};
//
//}
//
//template <
//        typename List,
//        bool IsRoot2Node,
//        typename SrcList = List,
//        typename Result = NullType
//>
//class Node2NodeMapTool {
//    typedef typename NodeFilter<
//                        ValueOp<ROOT, EQ, bool, IsRoot2Node>,
//                        List
//                     >::Result                                                  TargetList;
//public:
//    typedef typename intrnl::Node2NodeMapBuilderTool<TargetList, SrcList>::Map  Map;
//};
//
//
//
//
//
//template <
//    typename LevelList,
//    typename NodeTypeList,
//    typename RootNode,
//    typename LeafNode,
//    typename RootLeafNode,
//    typename Node,
//    typename NodeBase,
//    typename PageMgr,
//    typename Txn
//    >
//class NodeFactoryHelper;
//
//template <
//    typename NodeTypeList,
//    typename RootNode,
//    typename LeafNode,
//    typename RootLeafNode,
//    typename Node,
//    typename NodeBase,
//    typename PageMgr,
//    typename Txn
//    >
//class NodeFactoryHelper<NullType, NodeTypeList, RootNode, LeafNode, RootLeafNode, Node, NodeBase, PageMgr, Txn> {
//public:
//    static NodeBase *Create(PageMgr &mgr, Int level, bool root, bool leaf) {
//        NodeBase* node;
//        if (!root && !leaf) {
//            node = new (mgr) Node;
//            node->page_type_hash() = Node::hash();
//        }
//        else if (!root && leaf) {
//            node = new (mgr) LeafNode;
//            node->page_type_hash() = LeafNode::hash();
//        }
//        else if (root && !leaf) {
//            node = new (mgr) RootNode;
//            node->page_type_hash() = RootNode::hash();
//        }
//        else {
//            node = new (mgr) RootLeafNode;
//            node->page_type_hash() = RootLeafNode::hash();
//        }
//
//        node->level() = level;
//        node->set_root(root);
//        node->set_leaf(leaf);
//
//        return node;
//    }
//};
//
//
//template <
//    typename Head,
//    typename Tail,
//    typename NodeTypeList,
//    typename DefRootNode,
//    typename DefLeafNode,
//    typename DefRootLeafNode,
//    typename DefNode,
//    typename NodeBase,
//    typename PageMgr,
//    typename Txn
//    >
//class NodeFactoryHelper<TypeList<Head, Tail>, NodeTypeList, DefRootNode, DefLeafNode, DefRootLeafNode, DefNode, NodeBase, PageMgr, Txn> {
//
//    static const Int Level = Head::Value;
//
//    typedef typename NodeFilter<ValueOp<LEVEL, EQ, Short, Level>, NodeTypeList>::Result LevelList;
//
//    struct BaseWrapper {
//        typedef NodeBase Type;
//    };
//
//    template <bool Root, bool Leaf>
//    struct ListBuilder {
//        typedef typename SelectHeadIfNotEmpty <
//                typename NodeFilter <
//                    And <
//                        ValueOp<ROOT, EQ, bool, Root>,
//                        ValueOp<LEAF, EQ, bool, Leaf>
//                    >,
//                    LevelList
//                >::Result,
//                BaseWrapper
//        >::Result                                                               Type;
//    };
//
//    typedef typename ListBuilder<false, false>::Type                            Node;
//    typedef typename ListBuilder<false, true>::Type                             LeafNode;
//    typedef typename ListBuilder<true, false>::Type                             RootNode;
//    typedef typename ListBuilder<true, true>::Type                              RootLeafNode;
//
//public:
//    static NodeBase *Create(PageMgr &mgr, Int level, bool root, bool leaf) {
//        if (Level == level)
//        {
//            NodeBase* node;
//
//            if (!root && !leaf)
//            {
//                node = new (mgr) Node;
//                node->page_type_hash() = Node::hash();
//            }
//            else if (!root && leaf)
//            {
//                node = new (mgr) LeafNode;
//                node->page_type_hash() = LeafNode::hash();
//            }
//            else if (root && !leaf)
//            {
//                node = new (mgr) RootNode;
//                node->page_type_hash() = RootNode::hash();
//            }
//            else
//            {
//                node = new (mgr) RootLeafNode;
//                node->page_type_hash() = RootLeafNode::hash();
//            }
//
//            node->level() = level;
//            node->set_root(root);
//            node->set_leaf(leaf);
//
//            return node;
//        }
//        else {
//            return NodeFactoryHelper<
//                        Tail,
//                        NodeTypeList,
//                        DefRootNode,
//                        DefLeafNode,
//                        DefRootLeafNode,
//                        DefNode,
//                        NodeBase,
//                        PageMgr,
//                        Txn
//                   >::Create(mgr, level, root, leaf);
//        }
//    }
//};
//
//template <bool Root, bool Leaf, typename NodeTypeList>
//class FindNodeWithMaxLevelTool {
//    typedef typename NodeFilter<
//                And <
//                    ValueOp<ROOT, EQ, bool, Root>,
//                    ValueOp<LEAF, EQ, bool, Leaf>
//                >,
//                NodeTypeList
//    >::Result                                                                   SubList;
//public:
//    typedef typename Sorter<NodeDescriptorMetadata, false, LEVEL, SubList>::Result::Head Type;
//};
//
//
//template <
//    typename NodeTypeList,
//    typename NodeBase,
//    typename PageMgr,
//    typename Txn
//>
//class NodeFactoryTool: public NodeFactoryHelper <
//                                typename LevelListBuilder<NodeTypeList>::List,
//                                NodeTypeList,
//
//                                typename FindNodeWithMaxLevelTool<true,  false, NodeTypeList>::Type,
//                                typename FindNodeWithMaxLevelTool<false, true,  NodeTypeList>::Type,
//                                typename FindNodeWithMaxLevelTool<true,  true,  NodeTypeList>::Type,
//                                typename FindNodeWithMaxLevelTool<false, false, NodeTypeList>::Type,
//
//                                NodeBase,
//                                PageMgr,
//                                Txn
//                          >
//{};
//
//template <typename NodeBase, typename NodeList, typename List2 = NodeList> class NodeDispatcherTool;
//
//template <typename NodeBase, typename List2>
//class NodeDispatcherTool<NodeBase, NullType, List2> {
//public:
//    template <typename Functor>
//    static void Dispatch(NodeBase *, Functor &) {
//        std::cout<<"Can't dispatch 1"<<std::endl;
//    }
//
//    template <typename Functor>
//    static void Dispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    template <typename Functor>
//    static void DoubleDispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    template <typename Functor>
//    static void Dispatch2(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    static void BuildMetadataList(MetadataList &list) {}
//};
//
//
//template <typename NodeBase, typename List>
//class NodeDispatcherTool<NodeBase, List, NullType> {
//public:
//    template <typename Functor>
//    static void Dispatch(NodeBase *, Functor &) {
//        std::cout<<"Can't dispatch 2"<<std::endl;
//    }
//
//    template <typename Functor>
//    static void Dispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    template <typename Functor>
//    static void DoubleDispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    template <typename Functor>
//    static void Dispatch2(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    static void BuildMetadataList(MetadataList &list) {}
//};
//
//template <typename NodeBase>
//class NodeDispatcherTool<NodeBase, NullType, NullType> {
//public:
//    template <typename Functor>
//    static void Dispatch(NodeBase *, Functor &) {
//        std::cout<<"Can't dispatch 3"<<std::endl;
//    }
//
//    template <typename Functor>
//    static void Dispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    template <typename Functor>
//    static void DoubleDispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    template <typename Functor>
//    static void Dispatch2(NodeBase *node1, NodeBase *node2, Functor &functor) {}
//
//    static void BuildMetadataList(MetadataList &list) {}
//};
//
//
//template <typename NodeBase, typename Head1, typename Tail1, typename Head2, typename Tail2>
//class NodeDispatcherTool<NodeBase, TypeList<Head1, Tail1>, TypeList<Head2, Tail2> > {
//    static const bool   Root1  = Head1::Descriptor::Root;
//    static const bool   Leaf1  = Head1::Descriptor::Leaf;
//    static const BigInt Level1 = Head1::Descriptor::Level;
//
//    static const bool   Root2  = Head2::Descriptor::Root;
//    static const bool   Leaf2  = Head2::Descriptor::Leaf;
//    static const BigInt Level2 = Head2::Descriptor::Level;
//
//public:
//    template <typename Functor>
//    static void Dispatch(NodeBase *node, Functor &functor) {
//        bool level1EQ = Level1 == ANY_LEVEL ? true : Level1 == node->level();
//
//        if (level1EQ && Root1 == node->is_root() && Leaf1 == node->is_leaf()) {
//            functor(static_cast<Head1*>(node));
//        }
//        else {
//            NodeDispatcherTool<NodeBase, Tail1>::Dispatch(node, functor);
//        }
//    }
//
//    template <typename Functor>
//    static void Dispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {
//        bool level1EQ = Level1 == ANY_LEVEL ? true : Level1 == node1->level();
//
//        if (level1EQ && Root1 == node1->is_root() && Leaf1 == node1->is_leaf()) {
//            functor(static_cast<Head1*>(node1), static_cast<Head1*>(node2));
//        }
//        else {
//            NodeDispatcherTool<NodeBase, Tail1>::Dispatch(node1, node2, functor);
//        }
//    }
//
//    template <typename Functor>
//    static void DoubleDispatch(NodeBase *node1, NodeBase *node2, Functor &functor) {
//        bool level1EQ = Level1 == ANY_LEVEL ? true : Level1 == node1->level();
//        if (level1EQ && Root1 == node1->is_root() && Leaf1 == node1->is_leaf()) {
//            Dispatch2(node1, node2, functor);
//        }
//        else {
//            NodeDispatcherTool<NodeBase, Tail1, TypeList<Head2, Tail2> >::DoubleDispatch(node1, node2, functor);
//        }
//    }
//
//
//    template <typename Functor>
//    static void Dispatch2(NodeBase *node1, NodeBase *node2, Functor &functor) {
//        bool level2EQ = Level2 == ANY_LEVEL ? true : Level2 == node2->level();
//
//        if (level2EQ && Root2 == node2->is_root() && Leaf2 == node2->is_leaf()) {
//            functor(
//                static_cast<Head1*>(node1),
//                static_cast<Head2*>(node2)
//            );
//        }
//        else {
//            NodeDispatcherTool<NodeBase, TypeList<Head1, Tail1>, Tail2>::Dispatch2(node1, node2, functor);
//        }
//    }
//
//    static void BuildMetadataList(MetadataList &list) {
//        Head1::Init();
//        list.push_back(Head1::reflection());
//        NodeDispatcherTool<NodeBase, Tail1, Tail1>::BuildMetadataList(list);
//    }
//};
//
//
//
//template <
//    typename NodeTypesList,
//    typename NodeBase,
//    typename PageMgr,
//    typename Txn,
//    typename SuperType = EmptyType
//>
//class BTreeModelDispatchersBuilder: public SuperType {
//
//    typedef typename Sorter<
//                NodeDescriptorMetadata,
//                true,
//                LEVEL,
//                NodeTypesList
//    >::Result                                                                   NodeList;
//
//    typedef typename NodeFilter<ValueOp<ROOT, EQ, bool, true>,  NodeList>::Result RootList;
//    typedef typename NodeFilter<ValueOp<LEAF, EQ, bool, true>,  NodeList>::Result LeafList;
//    typedef typename NodeFilter<ValueOp<LEAF, EQ, bool, false>, NodeList>::Result NonLeafList;
//    typedef typename NodeFilter<ValueOp<ROOT, EQ, bool, false>, NodeList>::Result NonRootList;
//
//public:
//
//    typedef NodeDispatcherTool<NodeBase, NodeList>                              NodeDispatcher;
//    typedef NodeDispatcherTool<NodeBase, RootList>                              RootDispatcher;
//    typedef NodeDispatcherTool<NodeBase, LeafList>                              LeafDispatcher;
//    typedef NodeDispatcherTool<NodeBase, NonLeafList>                           NonLeafDispatcher;
//    typedef NodeDispatcherTool<NodeBase, NonRootList>                           NonRootDispatcher;
//
//    typedef typename Node2NodeMapTool<NodeList, true>::Map                      Root2NodeMap;
//    typedef typename Node2NodeMapTool<NodeList, false>::Map                     Node2RootMap;
//
//    typedef NodeFactoryTool<NodeList, NodeBase, PageMgr, Txn>                   NodeFactory;
//};
//
//
//}
//}
//}
//}

#endif // _CUBEFS_CORE_BTREE_PAGES_DISPATCHERS_HPP